package tjs.study.mini.spring;

import tjs.study.mini.spring.register.BeanDefinitionRegistry;
import tjs.study.mini.spring.register.BeanDefinitionRegistryPostProcessor;
import tjs.study.mini.spring.register.BeanFactory;

/**
 * Created by Nicky.Tang on 2021/9/13 3:34 下午
 *
 * @since 02.12.10
 */
public abstract class AbstractApplicationContext implements BeanDefinitionRegistry, BeanFactory {
    private Class<?>[] componentClasses;

    public AbstractApplicationContext(Class<?>... componentClasses) {
        this.componentClasses = componentClasses;
    }

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
        getBeanFactory().registerBeanDefinition(beanName, beanDefinition);
    }

    @Override
    public void removeBeanDefinition(String beanName) {
        getBeanFactory().removeBeanDefinition(beanName);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) {
        return getBeanFactory().getBeanDefinition(beanName);
    }

    @Override
    public boolean containsBeanDefinition(String beanName) {
        return getBeanFactory().containsBeanDefinition(beanName);
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return getBeanFactory().getBeanDefinitionNames();
    }

    @Override
    public Object getBean(String name) {
        return getBeanFactory().getBean(name);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) {
        return getBeanFactory().getBean(name, requiredType);
    }

    @Override
    public boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    public void refresh() {
        DefaultListableBeanFactory beanFactory = getBeanFactory();
        // 扫描bean
        invokeBeanFactoryPostProcessors(beanFactory);

        // 预留子类重写
        onRefresh();

        // 实例化bean
        finishBeanFactoryInitialization(beanFactory);
    }


    public abstract DefaultListableBeanFactory getBeanFactory();

    protected void invokeBeanFactoryPostProcessors(DefaultListableBeanFactory beanFactory) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;

        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class);
        for (String postProcessorName : postProcessorNames) {
            BeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = beanFactory.getBean(postProcessorName, BeanDefinitionRegistryPostProcessor.class);
            beanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry(registry, this.componentClasses);
        }

    }


    protected void onRefresh() {

    }

    protected void finishBeanFactoryInitialization(DefaultListableBeanFactory beanFactory) {

    }
}
